package cn.itsource.hrm.service.impl;

import cn.itsource.hrm.constant.RedisConstant;
import cn.itsource.hrm.dto.SMSSendDto;
import cn.itsource.hrm.exception.GlobalException;
import cn.itsource.hrm.service.IVerifycodeService;
import cn.itsource.hrm.util.AssertUtils;
import cn.itsource.hrm.util.StrUtils;
import cn.itsource.hrm.util.ValidatorUtils;
import cn.itsource.hrm.util.VerifyCodeUtils;
import cn.itsource.hrm.vo.SMSSendCodeVO;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Date;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class VerifycodeServiceImpl implements IVerifycodeService {

    @Autowired
    private StringRedisTemplate template;


    //1.判断 key 是否为空，提醒用户刷新一次 重新获取key
    //2.生成一个随机的数 uuid
    //3.根据key保存code 到rides, 添加过期时间
    //3 弄一张图片，通过工具类就实现
    //4.把图片转换为base64，返回 ;.

    @Override
    public String imageCode(String imageCodeKey) {
        //1.判断 key 是否为空，提醒用户刷新一次 重新获取key
        AssertUtils.isnotNull("key为空，请刷新浏览器重试",imageCodeKey);
        //2.生成一个随机的数 uuid
        String code = StrUtils.getRandomString(4);
        //3.根据key保存code 到rides, 添加过期时间
        template.opsForValue().set(imageCodeKey,code,5, TimeUnit.MINUTES);
        //3 弄一张图片，通过工具类就实现
        try {
            //4.把图片转换为base64，返回 ;.
            return VerifyCodeUtils.verifyCode(140, 50, code);
        } catch (IOException e) {
            e.printStackTrace();
            throw new GlobalException("验证码生成失败，请联系管理员");
        }

    }

    @Override
    public void sendSmsCode(SMSSendDto dto) {
        // 1. 验证参数 -非空校验
        String imageCode = dto.getImageCode();
        String imageCodeKey = dto.getImageCodeKey();
        String mobile = dto.getMobile();
        AssertUtils.isnotNull("图片验证码，不能为空",imageCode);
        AssertUtils.isnotNull("没有key,请刷新重试",imageCodeKey);
        AssertUtils.isRegIlegal("非法的手机号", ValidatorUtils.REG_Moblie,mobile);

        // 2. 取出Redis中的图片验证码 对比
        String oldImageCode = template.opsForValue().get(imageCodeKey);
        AssertUtils.isnotNull("图片验证码证码不正确,请刷新重试",oldImageCode);
        AssertUtils.isNotEquals("图片验证码不正确",imageCode,oldImageCode);
        //图片验证成功，删除之前的验证码
        template.delete(imageCodeKey);

        // 3. 看Redis中是否有之前生成的短信验证码，
        String key = String.format(RedisConstant.SEND_SMS_KEY, mobile);
        String jsonStr = template.opsForValue().get(key);
        SMSSendCodeVO smsSendCodeVO = JSON.parseObject(jsonStr, SMSSendCodeVO.class);
        Date now = new Date();
        String smsCode = null;
        if(smsSendCodeVO!=null){
            // 之前redis里面存的有code
            smsCode = smsSendCodeVO.getSmsCode();
            Date sendDate = smsSendCodeVO.getSendDate();
            // 4. 有的话，判断是否频繁60s
            long time = now.getTime() - sendDate.getTime();
            if(time/10000 < 120){
                throw new GlobalException("频繁发送，请稍后在试！");
            }

        }else{
            // 5. 如果没有存，自己生成一个 短信验证码
            smsCode = StrUtils.getRandomString(6);
            // 6. 保存到redis
            SMSSendCodeVO vo = new SMSSendCodeVO();
            vo.setSendDate(now);
            vo.setSmsCode(smsCode);
            template.opsForValue().set(key,JSON.toJSONString(vo),5,TimeUnit.MINUTES);
        }

        // 7. 调用短信feign 发送短信 -- 》 消息队列
        log.info("你的验证码是：{}，请尽快使用！",smsCode);

        // 8. 记录日志;

    }
}
